이 노트북은 제이크 반더플라스(Jake VanderPlas)의 A Whirlwind Tour of Python(OReilly Media, 2016)를 기반으로 만들어졌습니다. 이 내용은 CC0 라이센스를 따릅니다. 전체 노트북의 목록은 https://github.com/rickiepark/WhirlwindTourOfPython 에서 볼 수 있습니다.

< 모듈과 패키지 | 목차 | 데이터 과학 도구 소개 >

문자열과 정규 표현식

파이썬 언어가 뛰어난 한 분야가 문자열 처리입니다. 이 절은 파이썬의 내장 문자열 함수와 포맷팅 연산을 다룹니다. 그 다음에 아주 중요한 정규 표현식을 소개하겠습니다. 문자열 조작 패턴은 데이터 과학 작업에 자주 등장하고 파이썬의 큰 장점 중 하나입니다.

파이썬에서 문자열은 홑따옴표와 겹따옴표를 사용해 정의할 수 있습니다(두 가지 모두 동일합니다):

세 따옴표로 여러 줄의 문자열을 정의할 수도 있습니다:

파이썬의 문자열 처리 도구를 빠르게 살펴 보겠습니다.

파이썬의 간단한 문자열 처리 기능

기본적인 문자열 처리를 하는데 파이썬의 내장 문자열 메서드는 매우 편리합니다. C나 다른 저수준 언어를 사용한 경험이 있다면 파이썬의 메서드의 단순함이 아주 신선하게 느껴질 것입니다. 파이썬의 문자열 타입과 몇 개의 메서드를 앞서 소개했습니다. 여기서 조금 더 자세히 살펴 보겠습니다.

문자열 포맷팅: 대소문자 조정

파이썬에서는 문자열의 대소문자를 조정하는 것이 아주 쉽습니다. 여기에서는 upper(), lower(), capitalize(), title()swapcase() 메서드를 살펴 보겠습니다. 예제를 위해 다음과 같이 좀 이상한 문자열을 사용합니다:

전체 문자열을 대문자나 소문자로 바꾸려면 upper()lower() 메서드를 사용합니다:

일반적으로 포맷팅이 필요한 때는 각 단어의 첫 문자를 대문자로 바꾸거나 각 문장의 첫 글자를 대문자로 바꿀 때입니다. title()이나 capitalize() 메서드를 사용하면 됩니다:

대소문자를 바꾸어야 할 때는 swapcase() 메서드를 사용합니다:

문자열 포맷팅: 공백 추가 또는 삭제

자주 사용하는 또 다른 경우는 문자열 시작과 끝에서 공백(또는 다른 문자)을 제거할 때입니다. 문자를 제거하는 기본 메서드는 문자열의 시작과 끝에서 공백을 삭제하는 strip() 메서드입니다:

오른쪽과 왼쪽의 공백을 삭제하려면 rstrip() 또는 lstrip()를 사용합니다:

공백 대신 다른 문자를 삭제하려면 원하는 문자를 strip() 메서드에 전달하면 됩니다:

이 연산과 반대로 공백이나 다른 문자를 추가하려면 center(), ljust(), 그리고 rjust() 메서드를 사용합니다.

예를 들어 center() 메서드를 사용하여 문자열을 중앙에 두고 좌우에 지정한 길이에 맞게 공백을 넣을 수 있습니다:

비슷하게 ljust()rjust()는 주어진 길이에 맞게 왼쪽과 오른쪽으로 정렬합니다:

이 메서드들은 공백을 채우는데 사용할 문자를 추가로 받을 수 있습니다. 예들 들어:

0으로 채우는 작업이 빈번하기 때문에 파이썬은 0으로 문자열 오른쪽을 채우는 zfill() 메서드도 제공합니다:

부분 문자열 찾고 바꾸기

문자열에서 특정 문자를 찾고 싶다면 내장 메서드 find()/rfind(), index()/rindex(), 그리고 replace()를 사용합니다.

find()index()는 문자열에서 문자나 부분 문자열의 첫 번째 위치를 찾고 부분 문자열의 인덱스를 반환하는 점에서 매우 비슷합니다:

find()index()의 유일한 차이는 검색 문자열이 발견되지 않았을 때 처리 방식입니다. find()는 -1을 반환하고 index()ValueError 예외를 발생시킵니다:

rfind()rindex()도 문자열의 시작이 아니라 끝에서 부터 찾는 다는 것을 제외하고는 비슷합니다:

문자열의 시작과 끝의 부분 문자열을 체크하는 경우를 위해 파이썬에는 startswith()endswith() 메서드가 있습니다:

한 걸음 더 나아가 새로운 문자열로 부분 문자열을 바꾸려면 replace() 메서드를 사용합니다. 'brown''red'로 바꾸어 보겠습니다:

replace() 함수는 새로운 문자열을 반환하고 발견되는 모든 문자열을 바꿉니다:

replace()보다 더 유연한 기능을 원하면 정규 표현식을 사용한 유연한 패턴 매칭에서 정규 표현식에 대해 알아 보세요.

문자열 분리와 분할

부분 문자열을 찾아 그 위치에서 문자열을 나누고 싶다면 partition()이나 split() 메서드를 사용할 수 있습니다. 둘 다 부분 문자열의 시퀀스를 반환합니다.

partition() 메서드는 세 개로 이루어진 튜플을 반환합니다. 분할 위치 이전의 부분 문자열과 분할 문자열, 그리고 그 이후의 부분 문자열입니다:

rpartition() 메서드는 문자열의 오른쪽에서부터 찾는다는 것을 제외하면 비슷합니다.

split() 메서드는 더 유용합니다. 모든 분할 위치를 찾고 그 사이의 부분 문자열을 반환합니다. 기본값은 공백 문자를 기준으로 분할하고 문자열에 있는 단어의 리스트를 반환합니다:

유사한 메서드는 splitlines()로 줄바꿈 문자열을 기준으로 분할합니다. 17세기 시인 마쓰오 바쇼(Matsuo Bashō)로 유명한 하이쿠(Haiku)에 적용해 보겠습니다:

split()를 반대로 하고 싶다면 분할 문자와 반복 객체로 부터 문자열을 만들어 반환하는 join() 메서드를 사용합니다:

이전에 분할했던 라인들을 "\n"(줄바꿈) 문자로 합쳐서 입력을 복원하는 것이 흔한 패턴입니다:

포맷 문자열

앞선 메서드에서 문자열에서 값을 추출하는 것과 원하는 형태로 문자열을 조작하는 방법을 배웠습니다. 문자열 메서드의 다른 사용법은 다른 타입의 값을 문자열로 표현하는 것입니다. 물론 문자열 표현은 str() 함수를 사용하여 만들 수 있습니다. 예를 들어:

더 복잡한 포맷에는 연산자에서 보았던 문자열 연산을 사용할 수 있습니다:

더 유연한 방법은 포맷 문자열을 사용하는 것입니다. 문자열로 포맷팅된 값이 삽입되는 특별한 마커(중괄호)가 있는 문자열입니다. 다음이 기본적인 예입니다:

{} 마커 안에 표시하고 싶은 것이 정확히 무엇인지 정보를 넣을 수 있습니다. 숫자를 넣으면 삽입하려는 매개변수의 인덱스를 의미합니다:

문자열을 넣으면 키워드 매개변수의 키를 의미합니다:

마지막으로 숫자 입력을 위해 문자열로 바뀌는 형식을 제어하기 위한 포맷 코드를 넣을 수 있습니다. 예를 들어 소숫점 뒤에 세 자리를 가진 부동 소수로 숫자를 출력하기 위해 다음과 같이 쓸 수 있습니다:

이전처럼 "0"은 삽입되는 값의 인덱스를 의미합니다. ":" 표시 뒤에는 포맷 코드가 나옵니다. ".3f"는 원하는 정밀도를 나타냅니다. 소숫점 뒤에 세 자리를 가진 부동 소수 포맷입니다.

이런 포맷 스타일은 매우 유연합니다. 여기의 예제는 매우 일부이며 가능한 포맷팅이 매우 많습니다. 포맷 문자열의 문법에 관한 더 많은 정보는 파이썬 온라인 문서의 포맷 규약을 참고하세요.

정규 표현식을 사용한 유연한 패턴 매칭

파이썬의 str 타입의 메서드는 포맷팅, 분할, 데이터 처리에 관한 강력한 도구들을 제공해 줍니다. 하지만 더욱 강력한 도구가 파이썬의 내장 정규 표현식 모듈에서 제공됩니다. 정규 표현식은 매우 넓은 주제입니다. 이 주제에 대해서 쓴 책들이 있습니다(Jeffrey E.F. Friedl의 Mastering Regular Expressions, 3rd Edition도 포함됩니다). 그래서 하나의 섹션으로 다루긴 매우 힘듭니다.

여기서의 목표는 정규 표현식을 사용해야 하는 문제가 어떤 것인지 감을 잡고 파이썬에서 이를 어떻게 사용하는지 기초를 배우는 것입니다. 더 자세한 내용은 정규 표현식을 위한 참고 자료를 확인하세요.

기본적으로 정규 표현식은 문자열의 유연한 패턴 매칭을 의미합니다. 명령행을 많이 사용한다면 와일드 카드처럼 작동하는 "*" 문자 때문에 이런 매칭에 친숙할지 모릅니다. 예를 들어, 파일 이름에 "파이썬"이 포함된 모든 IPython 노트북을 (즉, .html로 끝나는 파일들) "*" 와일드카드를 사용하여 그 사이의 어떤 문자와도 매칭하여 출력할 수 있습니다:

정규 표현식은 이런 와일드카드 문자를 문자열 매칭 문법으로 크게 확장하여 일반화시킨 것입니다. 정규 표현식에 대한 파이썬의 인터페이스는 내장 re 모듈에 있습니다. 간단한 예로 split() 메서드의 기능을 똑같이 만들어 보겠습니다:

먼저 정규 표현식을 컴파일하고 이를 사용해 문자열을 분할했습니다. 파이썬의 split() 메서드가 공백 사이의 모든 부분 문자열을 리스트로 반환하는 것처럼 정규 표현식의 split() 메서드는 입력 패턴에 매칭되는 것 사이의 모든 부분 문자열을 리스트로 반환합니다.

이 경우에 입력은 "\s+"입니다. "\s+"는 어떤 공백 문자(공백, 탭, 줄바꿈 등)와도 매칭되는 특별한 문자입니다. "+"는 그 앞의 요소가 하나 또는 그 이상을 의미하는 문자입니다. 그러므로 이 정규 표현식은 하나 또는 그 이상의 공백으로 이루어진 모든 부분 문자열에 매칭됩니다.

split() 메서드는 이런 패턴 매칭 방식을 위해 구현된 편의 기능입니다. 조금 더 기본적인 것은 문자열의 시작이 패턴에 매칭되는지 알려 주는 match() 메서드입니다:

split()와 같이 (str.index()str.find()처럼) 첫 번째 매칭을 찾거나 (str.replace()처럼) 찾아서 바꾸는 편리한 루틴이 있습니다. 이전의 문자열을 다시 사용하겠습니다:

regex.search() 메서드가 str.index()str.find()와 매우 비슷하게 작동하는 것을 볼 수 있습니다:

비슷하게 regex.sub() 메서드는 str.replace()와 비슷하게 동작합니다:

조금 생각해 보면 다른 기본 문자열 연산도 정규 표현식으로 바꿀 수 있습니다.

더 복잡한 예제

하지만 왜 간단하고 쉬운 문자열 메서드 대신에 복잡하고 번거로운 정규 표현식 문법을 사용해야 할까요? 정규 표현식을 사용하는 장점은 더욱 유연하기 때문입니다.

다음에 조금 더 복잡한 예를 살펴 보겠습니다. 이메일 주소를 매칭하는 작업은 흔하게 발생합니다. 일단 정규 표현식을 하나 쓰고 (조금 난해하지만) 무엇을 의미하는지 알아 보겠습니다:

이를 사용하면 주어진 한 줄 텍스트에서 이메일 주소로 보이는 것을 빠르게 추출할 수 있습니다.

(이 주소는 예제를 위해 만든 것입니다. 귀도와 연락하려면 다른 방법을 찾으세요.)

이메일 주소를 다른 문자열로 바꾸어 출력에서 이메일 주소를 감추는 등의 다른 작업을 할 수 있습니다:

마지막으로 어떤 이메일 주소와도 매칭하고 싶다면 앞선 정규 표현식은 너무 간단합니다. 예를 들어 일반적인 도메인 주소로 끝나는 알파벳과 숫자로된 주소만 매칭이 됩니다. 그래서 예를 들어 콤마를 사용하면 주소의 일부만 찾을 수 있습니다:

이는 주의하지 않으면 얼마나 정규 표현식이 실수하기 쉬운지를 보여줍니다! 온라인에서 찾아보면 모든 올바른 이메일에 매칭되는 정규 표현식의 예를 찾을 수 있습니다. 하지만 주의하세요. 여기서 사용한 간단한 표현식보다 훨씬 복잡할 것입니다!

정규 표현식의 기본 문법

정규 표현식의 문법은 작은 섹션에 담기에는 너무 큰 주제입니다. 친숙해지려면 꽤 시간이 걸립니다. 여기서는 기본적인 구성을 조금 다루고 더 배울 수 있는 참고 자료를 제시하겠습니다. 다음의 간략한 소개가 다른 참고 자료를 사용하는데 도움이 되었으면 좋겠습니다.

간단한 문자열은 직접 매칭됩니다

문자나 숫자로 이루어진 간단한 문자열의 정규 표현식을 만들면 정확히 같은 문자열에 매칭됩니다:

일부 문자들은 특별한 의미를 가집니다

단순한 문자나 숫자가 직접 매칭되는 반면 정규 표현식 내에서 특별한 의미를 가지는 문자들이 조금 있습니다:

. ^ $ * + ? { } [ ] \ | ( )

잠시 후에 이 문자들의 의미를 알아 보겠습니다. 그 전에 이런 문자들을 직접 매칭하려면 역 슬래시로 이런 문자를 이스케이프해야 합니다:

r'\$'에서 r 접두어는 원본 문자열을 의미합니다. 표준 파이썬 문자열에서 역 슬래시는 특별한 문자를 지칭하기 위해 사용됩니다. 예를 들어 탭은 "\t"로 나타냅니다:

원본 문자열에서는 이런 치환이 일어나지 않습니다:

그러므로 정규 표현식에서 역 슬래시를 사용할 땐 원본 문자열을 사용하는 것이 좋습니다.

특수 문자는 문자 그룹에 매칭할 수 있습니다

정규 표현식 안에 있는 "\" 문자가 특수 문자를 이스케이프해서 일반 문자로 바꿀 수 있는 것처럼 일반 문자에 특별한 의미를 부여할 수도 있습니다. 이런 특수 문자는 지정한 문자의 그룹에 매칭되고 이전에 이미 본 적이 있습니다. 이메일 주소 정규 표현식에서 어떤 알파벳과 숫자 문자에도 매칭되는 마커인 "\w" 문자를 사용했습니다. 비슷하게 split() 예제에서는 어떤 공백 문자와도 매칭되는 "\s"를 보았습니다.

이들을 모두 합치면 공백으로 나뉘어진 어떤 두 개의 문자나 숫자를 매칭하는 정규 표현식을 만들 수 있습니다:

이 예제에서 정규 표현식의 강력함과 유연함을 엿볼 수 있습니다.

다음 테이블은 자주 사용하는 이런 문자들을 정리해 놓은 것입니다:

문자 설명 문자 설명
"\d" 숫자에 매칭 "\D" 숫자가 아닌 것에 매칭
"\s" 공백문자에 매칭 "\S" 공백 문자가 아닌 것에 매칭
"\w" 알파벳과 숫자에 매칭 "\W" 알파벳과 숫자가 아닌 것에 매칭

이는 전체 리스트와 설명이 아닙니다. 더 자세한 내용은 파이썬의 정규 표현식 문법 문서를 보세요.

대괄호는 임의의 문자 그룹과 매칭합니다

기본 문자 그룹이 충분하지 않다면 대괄호를 사용해 원하는 어떤 문자 집합을 지정할 수 있습니다. 예를 들어 다음은 소문자 모음을 매칭합니다:

비슷하게 대시(-)를 사용하면 범위를 지정할 수 있습니다. 예를 들어 "[a-z]"는 어떤 소문자와도 매칭되고 "[1-3]""1", "2", 또는 "3"와 매칭합니다. 예를 들어 대문자 뒤에 하나의 숫자로 쓰여진 특별한 숫자 코드를 추출하려고 합니다. 다음과 같이 쓸 수 있습니다:

와일드카드는 반복된 문자에 매칭합니다

만약 차례대로 세 개의 알파벳이나 숫자 문자를 매칭하려면 "\w\w\w"와 같이 쓸 수 있습니다. 이런 일은 자주 생기기 때문에 반복을 매칭하는 특별한 문법인 중괄호로 감싼 숫자가 있습니다:

어떤 개수의 반복에도 매칭할 수 있는 마커도 있습니다. "+" 문자는 앞에 나오는 요소에 대해 하나 또는 그 이상의 반복에 매칭합니다:

다음 테이블은 정규 표현식에서 사용할 수 있는 반복 마커입니다:

문자 설명 예제
? 0개 또는 한 개에 매칭합니다 "ab?""a" 또는 "ab"에 매칭됩니다
* 0개 또는 그 이상에 매칭합니다 "ab*""a", "ab", "abb", "abbb"...에 매칭합니다
+ 한 개 또는 그 이상에 매칭합니다 "ab+""ab", "abb", "abbb"...에 매칭하지만 "a"는 아닙니다
{n} n번 반복에 매칭합니다 "ab{2}""abb"에 매칭합니다
{m,n} mn 반복 사이에 매칭합니다 "ab{2,3}""abb" 또는 "abbb"에 매칭합니다

이런 기본적인 사항을 기억해두고 이메일 주소의 예로 돌아가 보겠습니다:

이제 이 의미를 이해할 수 있습니다. 하나 또는 그 이상의 알파벳과 숫자 문자("\w+")와 그 뒤에 @ 문자("@"), 그 뒤에 하나 또는 그 이상의 알파벳과 숫자 문자("\w+"), 그 뒤에 마침표("\." - 역 슬래시로 이스케이프해야 합니다), 그 뒤에 세 개의 소문자 글자가 뒤따라야 합니다.

이를 오바마 이메일 주소와 매칭하도록 수정하려면 대괄호 표기를 사용할 수 있습니다:

"\w+"에서 "[\w.]+"로 바꾸었으므로 알파벳과 숫자 문자 또는 마침표와 매칭됩니다. 표현식을 더 확장하면 더 많은 이메일 주소와 매칭할 수 있습니다.

소괄호는 추출할 그룹을 지정합니다

이메일 주소 예제처럼 복합적인 정규 표현식에서 전체 매칭 대신 일부 요소를 추출하고 싶을 때가 있습니다. 소괄호를 사용하여 이런 결과를 그룹지을 수 있습니다:

여기서 보듯이 이런 그룹은 이메일 주소의 모든 부분 요소를 리스트로 추출합니다.

더 나아가 "(?P<name> )" 문법을 사용해 추출한 요소에 이름을 부여하여 파이썬 딕셔너리로 추출할수 있습니다:

이런 아이디어를 결합하면 (여기에서 언급하지 않은 강력한 정규 표현식 문법은 물론) 파이썬에서 문자열로부터 정보를 다양하고 빠르게 추출할 수 있습니다.

정규 표현식을 위한 참고 자료

이 섹션의 내용은 방대한 정규 표현식의 주제를 짧게 다룬 것입니다. 더 자세히 알고 싶다면 다음 자료를 추천합니다:

거시적으로 문자열 처리와 정규 표현식의 예제를 Pandas: Labeled Column-oriented Data에서 볼 수 있습니다. 판단스 패키지 내에서 문자열 데이터의 테이블에 이런 표현식을 적용하는 예입니다.

< 모듈과 패키지 | 목차 | 데이터 과학 도구 소개 >